

export default {

    /**
     * https://developer.mozilla.org/zh-CN/docs/Web/API/WebGLRenderingContext/getError
     */
    checkGLError(gl){
        let ret = gl.getError();
        if(ret !== gl.NO_ERROR){
            switch (ret) {
                case gl.INVALID_ENUM:
                    console.error('An unacceptable value has been specified for an enumerated argument. The command is ignored and the error flag is set.');
                    break;
                case gl.INVALID_VALUE:
                    console.error('A numeric argument is out of range. The command is ignored and the error flag is set.');
                    break;
                case gl.INVALID_OPERATION:
                    console.error('The specified command is not allowed for the current state. The command is ignored and the error flag is set.');
                    break;
                case gl.INVALID_FRAMEBUFFER_OPERATION:
                    console.error('The currently bound framebuffer is not framebuffer complete when trying to render to or to read from it.');
                    break;
                case gl.OUT_OF_MEMORY:
                    console.error('Not enough memory is left to execute the command.');
                    break;
                case gl.CONTEXT_LOST_WEBGL:
                    console.error('If the WebGL context is lost, this error is returned on the first call to getError. Afterwards and until the context has been restored, it returns gl.NO_ERROR.');
                    break;
                default:
                    console.error(`ret:${ret} error!`);
            }
        }
    },

    // shader
    createProgram(gl, vshader, fshader) {
        // Create shader object
        let vertexShader = this._loadShader(gl, gl.VERTEX_SHADER, vshader);
        let fragmentShader = this._loadShader(gl, gl.FRAGMENT_SHADER, fshader);
        if (!vertexShader || !fragmentShader) {
            return null;
        }

        // Create a program object
        let program = gl.createProgram();
        if (!program) {
            return null;
        }

        // Attach the shader objects
        gl.attachShader(program, vertexShader);
        gl.attachShader(program, fragmentShader);

        // Link the program object
        gl.linkProgram(program);

        // Check the result of linking
        let linked = gl.getProgramParameter(program, gl.LINK_STATUS);
        if (!linked) {
            let error = gl.getProgramInfoLog(program);
            console.error('Failed to link program: ' + error);
            gl.deleteProgram(program);
            gl.deleteShader(fragmentShader);
            gl.deleteShader(vertexShader);
            return null;
        }
        return program;
    },

    _loadShader(gl, type, source) {
        // Create shader object
        let shader = gl.createShader(type);
        if (shader == null) {
            console.error('unable to create shader');
            return null;
        }

        // Set the shader program
        gl.shaderSource(shader, source);

        // Compile the shader
        gl.compileShader(shader);

        // Check the result of compilation
        let compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
        if (!compiled) {
            let error = gl.getShaderInfoLog(shader);
            console.error('Failed to compile shader: ' + error);
            console.error(`source:${source}`);
            gl.deleteShader(shader);
            return null;
        }

        return shader;
    },

}